#include <iostream>
#include <string>
#include <chrono>


/*
请记住：
1、为内置型对象进行手工初始化，因为C不保证初始化它们。

2、构造函数最好使用成员初值列(memberinitializationlist)，而不要在构造函数本体内使用赋值操作(assignment)。
初值列列出的成员变量，其排列次序应该和它们在 class 中的声明次序相同。

3、为免除“跨编译单元之初始化次序”问题，请以1ocal static 对象替换 non-local static 对象。
*/

class AddressBookEntry
{

    private:
        std::string name;
        std::string phone;
        std::string email;
        const int time;//如果成员变量为cosnt类型，则必须使用initialize list初始化而非赋值(assignment)操作

    public:

        // AddressBookEntry(const std::string& n, const std::string& p, const std::string& e, int t)
        //     : name(n), phone(p), email(e), time(t)
        // {
        //     std::cout << "AddressBookEntry object created with name: " << name << std::endl;
        // }  


        //这个是赋值(assignment)操作而非初始化(initialization)操作
        //这种做法不是最佳的，正确做法应该是使用成员初始化列表(member initialization list)
        // AddressBookEntry(const std::string& n, const std::string& p, const std::string& e,int t)
        // {
        //     name = n;
        //     phone = p;
        //     email = e;
        //     time = t;
        //     std::cout << "AddressBookEntry object created with name: " << name << std::endl;
        // }
        
        //正确做法
        AddressBookEntry(const std::string& n, const std::string& p, const std::string& e)
            : name(n), phone(p), email(e), time(0)
        {
            std::cout << "AddressBookEntry object created with name: " << name << std::endl;
        }
        
};


/*两个编译单元之初始化次序问题*/
//无法确保跨编译单元之初始化次序问题，因为编译单元之间没有明确的依赖关系。


//FileSystem.h
class FileSystem {		//来自你的程序库
public:
    std::size_t numDisks() const;	//众多成员函数之一，返回size_t类型
};
extern FileSystem tfs;	//为客户使用而预留的对象。tfs = the file system

//Directory.h
class Directory {		//客户自定义处理文件系统的目录类
public:
    Directory();
};
Directory::Directory(){
    std::size_t disks = tfs.numDisks();	//使用tfs对象
}

//Directory.cpp
Directory tempDir();	//为临时文件而做出来的目录

//注意上例中两个构造函数的使用顺序：除非tfs在tempDir之前先被初始化，否则tempDir的构造函数会用到尚未初始化的tfs。
//但tfs和tempDir是定义在不同编译单元内的non-local static对象，无法保证tfs先于tempDir初始化。




// 使用Singleton模式实现封装 - 将non-local 转为 local
// 原理：C++保证函数内部的local static对象会在“该函数被调用期间”、“首次遇上该对象之定义式”时被初始化
// 做法：以“函数调用”（返回一个reference指向local static对象）替换“直接访问non-local static对象”
// 为什么值得做：
// 1.提供封装以保证任何调用顺序都有其逻辑正确性
// 2.如果不调用则节省了构造和析构成本

// 改进后的class设计
//FileSystem.h
class FileSystem {		//来自你的程序库
public:
    std::size_t numDisks() const;	//众多成员函数之一，返回size_t类型
};
FileSystem& tfs(){		//为客户使用而预留的对象。tfs = the file system
	static FileSystem fs;
	return fs;
}

//Directory.h
class Directory {		//客户自定义处理文件系统的目录类
public:
    Directory();
};
Directory::Directory(){
    std::size_t disks = tfs().numDisks();	//使用tfs对象
}
Directory& tempDir(){	//为临时文件而做出来的目录
	static Directory td;
	return td;
}




int main(int argc, char const *argv[])
{
    std::string name = "John Doe";
    std::string phone = "123-456-7890";
    std::string email = "johndoe@example.com";
    int time = 10;
    AddressBookEntry entry(name, phone, email);


    return 0;
}
